package com.example.demo.service;

import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.GlobalMemory;
import oshi.hardware.NetworkIF;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.software.os.OSProcess;
import org.springframework.stereotype.Service;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;

@Service
public class SystemInfoService {

    private final SystemInfo systemInfo;
    private final HardwareAbstractionLayer hardware;
    private final OperatingSystem operatingSystem;

    public SystemInfoService() {
        this.systemInfo = new SystemInfo();
        this.hardware = systemInfo.getHardware();
        this.operatingSystem = systemInfo.getOperatingSystem();
    }

    // 获取CPU信息
    public Map<String, Object> getCpuInfo() {
        Map<String, Object> cpuInfo = new HashMap<>();
        CentralProcessor processor = hardware.getProcessor();
        
        cpuInfo.put("name", processor.getProcessorIdentifier().getName());
        cpuInfo.put("physicalCores", processor.getPhysicalProcessorCount());
        cpuInfo.put("logicalCores", processor.getLogicalProcessorCount());
        cpuInfo.put("vendor", processor.getProcessorIdentifier().getVendor());
        cpuInfo.put("model", processor.getProcessorIdentifier().getModel());
        
        // 获取CPU使用率 - 参考文章中的实现方式
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        try {
            Thread.sleep(1000); // 使用1秒采样更准确
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long[] ticks = processor.getSystemCpuLoadTicks();
        
        // 计算CPU使用率
        double cpuUsage = (1.0 - 
            ((double) (ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()]) 
            / (sum(ticks) - sum(prevTicks)))) * 100;
            
        Map<String, Double> cpuLoad = new HashMap<>();
        cpuLoad.put("total", cpuUsage);
        
        // 添加系统负载
        cpuInfo.put("systemLoadAverage", processor.getSystemLoadAverage(1)[0]);
        cpuInfo.put("load", cpuLoad);
        
        return cpuInfo;
    }
    
    // 辅助方法：计算数组总和
    private long sum(long[] values) {
        long sum = 0;
        for (long value : values) {
            sum += value;
        }
        return sum;
    }

    // 获取内存信息
    public Map<String, Object> getMemoryInfo() {
        Map<String, Object> memoryInfo = new HashMap<>();
        GlobalMemory memory = hardware.getMemory();
        
        long totalBytes = memory.getTotal();
        long availableBytes = memory.getAvailable();
        long usedBytes = totalBytes - availableBytes;
        
        memoryInfo.put("total", totalBytes);
        memoryInfo.put("available", availableBytes);
        memoryInfo.put("used", usedBytes);
        memoryInfo.put("usagePercent", 100.0 * usedBytes / totalBytes);
        
        return memoryInfo;
    }

    // 获取磁盘信息
    public List<Map<String, Object>> getDiskInfo() {
        List<Map<String, Object>> diskInfos = new ArrayList<>();
        // 在oshi-core 6.2.2中，磁盘信息可以通过文件系统获取
        FileSystem fileSystem = operatingSystem.getFileSystem();
        List<OSFileStore> fileStores = fileSystem.getFileStores();
        
        for (OSFileStore store : fileStores) {
            if (store.getTotalSpace() > 1024 * 1024 * 1024) { // 只显示大于1GB的存储设备
                Map<String, Object> diskInfo = new HashMap<>();
                diskInfo.put("name", store.getName());
                diskInfo.put("model", store.getDescription());
                diskInfo.put("size", store.getTotalSpace());
                diskInfo.put("type", store.getType());
                diskInfos.add(diskInfo);
            }
        }
        
        return diskInfos;
    }

    // 获取文件系统信息
    public List<Map<String, Object>> getFileSystemInfo() {
        List<Map<String, Object>> fileSystemInfos = new ArrayList<>();
        FileSystem fileSystem = operatingSystem.getFileSystem();
        List<OSFileStore> fileStores = fileSystem.getFileStores();
        
        for (OSFileStore store : fileStores) {
            Map<String, Object> fsInfo = new HashMap<>();
            fsInfo.put("name", store.getName());
            fsInfo.put("description", store.getDescription());
            fsInfo.put("type", store.getType());
            fsInfo.put("totalSpace", store.getTotalSpace());
            fsInfo.put("usableSpace", store.getUsableSpace());
            fsInfo.put("usedSpace", store.getTotalSpace() - store.getUsableSpace());
            fsInfo.put("usagePercent", 100.0 * (store.getTotalSpace() - store.getUsableSpace()) / store.getTotalSpace());
            fsInfo.put("mountPoint", store.getMount());
            fileSystemInfos.add(fsInfo);
        }
        
        return fileSystemInfos;
    }

    // 获取进程信息
    public List<Map<String, Object>> getProcessInfo() {
        List<Map<String, Object>> processInfos = new ArrayList<>();
        // 在oshi-core 6.2.2中，获取进程列表的API有所变化
        List<OSProcess> processes = operatingSystem.getProcesses();
        
        // 按CPU使用率排序并限制数量
        // 在oshi-core 6.2.2中，应使用getProcessCpuLoadBetweenTicks获取CPU负载
        processes.sort((p1, p2) -> Double.compare(
                p2.getProcessCpuLoadBetweenTicks(p2) * 100,
                p1.getProcessCpuLoadBetweenTicks(p1) * 100
        ));
        
        // 只取前50个进程
        int limit = Math.min(50, processes.size());
        List<OSProcess> topProcesses = processes.subList(0, limit);
        
        for (OSProcess process : topProcesses) {
            Map<String, Object> processInfo = new HashMap<>();
            processInfo.put("pid", process.getProcessID());
            processInfo.put("name", process.getName());
            processInfo.put("command", process.getCommandLine());
            processInfo.put("cpuPercent", process.getProcessCpuLoadBetweenTicks(process) * 100);
            processInfo.put("memoryPercent", process.getResidentSetSize() * 100.0 / hardware.getMemory().getTotal());
            processInfo.put("user", process.getUser());
            processInfo.put("startTime", new Date(process.getStartTime()));
            processInfos.add(processInfo);
        }
        
        return processInfos;
    }

    // 获取主机信息
    public Map<String, Object> getHostInfo() {
        Map<String, Object> hostInfo = new HashMap<>();
        
        try {
            InetAddress localhost = InetAddress.getLocalHost();
            hostInfo.put("hostname", localhost.getHostName());
            hostInfo.put("ipAddress", localhost.getHostAddress());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        
        hostInfo.put("osName", operatingSystem.getFamily());
        hostInfo.put("osVersion", operatingSystem.getVersionInfo().getVersion());
        hostInfo.put("manufacturer", hardware.getComputerSystem().getManufacturer());
        hostInfo.put("model", hardware.getComputerSystem().getModel());
        
        return hostInfo;
    }

    // 获取网卡信息
    public List<Map<String, Object>> getNetworkInfo() {
        List<Map<String, Object>> networkInfos = new ArrayList<>();
        List<NetworkIF> networkIFs = hardware.getNetworkIFs();
        
        for (NetworkIF net : networkIFs) {
            // 更新网络统计信息
            net.updateAttributes();
            
            Map<String, Object> networkInfo = new HashMap<>();
            networkInfo.put("name", net.getName());
            networkInfo.put("displayName", net.getDisplayName());
            networkInfo.put("macAddress", net.getMacaddr());
            networkInfo.put("ipv4Addresses", Arrays.asList(net.getIPv4addr()));
            networkInfo.put("ipv6Addresses", Arrays.asList(net.getIPv6addr()));
            networkInfo.put("mtu", net.getMTU());
            networkInfo.put("speed", net.getSpeed());
            networkInfo.put("bytesRecv", net.getBytesRecv());
            networkInfo.put("bytesSent", net.getBytesSent());
            networkInfo.put("packetsRecv", net.getPacketsRecv());
            networkInfo.put("packetsSent", net.getPacketsSent());
            networkInfo.put("timeStamp", System.currentTimeMillis());
            networkInfos.add(networkInfo);
        }
        
        return networkInfos;
    }

    // 获取系统负载信息
    public Map<String, Object> getLoadInfo() {
        Map<String, Object> loadInfo = new HashMap<>();
        CentralProcessor processor = hardware.getProcessor();
        
        // 获取系统负载平均值（1分钟、5分钟、15分钟）
        double[] loadAverages = processor.getSystemLoadAverage(3);
        loadInfo.put("loadAverage1min", loadAverages[0]);
        loadInfo.put("loadAverage5min", loadAverages[1]);
        loadInfo.put("loadAverage15min", loadAverages[2]);
        
        // 添加CPU核心数信息
        loadInfo.put("processors", processor.getLogicalProcessorCount());
        
        return loadInfo;
    }
    
    // 获取系统运行时间信息
    public Map<String, Object> getUptimeInfo() {
        Map<String, Object> uptimeInfo = new HashMap<>();
        
        try {
            // 方法1：直接使用oshi提供的运行时间计算（毫秒）
            long uptimeMillis = operatingSystem.getSystemUptime() * 1000L; // 有些版本返回秒，转换为毫秒
            
            // 如果方法1失败，使用方法2：通过启动时间计算
            if (uptimeMillis <= 0) {
                long bootTime = operatingSystem.getSystemBootTime();
                // 确保bootTime是有效的（不是0或未来时间）
                if (bootTime > 0 && bootTime < System.currentTimeMillis()) {
                    uptimeMillis = System.currentTimeMillis() - bootTime;
                }
            }
            
            // 转换为天、时、分、秒
            long days = uptimeMillis / (24 * 60 * 60 * 1000);
            long hours = (uptimeMillis % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000);
            long minutes = (uptimeMillis % (60 * 60 * 1000)) / (60 * 1000);
            long seconds = (uptimeMillis % (60 * 1000)) / 1000;
            
            uptimeInfo.put("uptimeMillis", uptimeMillis);
            uptimeInfo.put("days", days);
            uptimeInfo.put("hours", hours);
            uptimeInfo.put("minutes", minutes);
            uptimeInfo.put("seconds", seconds);
            
            // 格式化输出，确保正确显示
            uptimeInfo.put("formatted", String.format("%d天 %02d:%02d:%02d", days, hours, minutes, seconds));
        } catch (Exception e) {
            // 异常处理，确保即使出现问题也能返回合理的默认值
            uptimeInfo.put("uptimeMillis", 0);
            uptimeInfo.put("days", 0);
            uptimeInfo.put("hours", 0);
            uptimeInfo.put("minutes", 0);
            uptimeInfo.put("seconds", 0);
            uptimeInfo.put("formatted", "0天 00:00:00");
            e.printStackTrace();
        }
        
        return uptimeInfo;
    }

    // 获取所有系统信息
    public Map<String, Object> getAllSystemInfo() {
        Map<String, Object> allInfo = new HashMap<>();
        allInfo.put("host", getHostInfo());
        allInfo.put("cpu", getCpuInfo());
        allInfo.put("memory", getMemoryInfo());
        allInfo.put("disks", getDiskInfo());
        allInfo.put("fileSystems", getFileSystemInfo());
        allInfo.put("networks", getNetworkInfo());
        allInfo.put("processes", getProcessInfo());
        allInfo.put("load", getLoadInfo());
        allInfo.put("uptime", getUptimeInfo());
        allInfo.put("timestamp", new Date());
        return allInfo;
    }
}